﻿using DepIC.Tests.Services;
using NUnit.Framework;

namespace DepIC.Tests
{
    [TestFixture]
    public class ContainerTests
    {
        [Test]
        public void Test_Get_Should_Return_The_Same_Instance_When_Lifetime_Is_PerContainer()
        {
            // Arrange
            var container = ContainerFactory.Create();

            container.SetImplementation<ITestService, TestService>(Lifetime.PerContainer);

            var firstInstance = container.Get<ITestService>();

            // Act
            var secondInstance = container.Get<ITestService>();

            // Assert
            Assert.AreSame(firstInstance, secondInstance);
        }

        [Test]
        public void Test_Get_Should_Return_Another_Instance_When_Lifetime_Is_PerCall()
        {
            // Arrange
            var container = ContainerFactory.Create();

            container.SetImplementation<ITestService, TestService>(Lifetime.PerCall);

            var firstInstance = container.Get<ITestService>();

            // Act
            var secondInstance = container.Get<ITestService>();

            // Assert
            Assert.AreNotSame(firstInstance, secondInstance);
        }

        [Test]
        public void Test_Get_Should_Return_Instance_When_SetConstant_Is_Used()
        {
            // Arrange
            var container = ContainerFactory.Create();

            var originalInstance = new TestService();

            container.SetConstant<ITestService, TestService>(originalInstance);

            // Act
            var returnedInstance = container.Get<ITestService>();

            // Assert
            Assert.AreSame(originalInstance, returnedInstance);
        }

        [Test]
        public void Test_Get_Should_Inject_Instance_Of_Service()
        {
            // Arrange
            var container = ContainerFactory.Create();

            var instance = new TestService();
            container.SetConstant<ITestService, TestService>(instance);

            container.SetImplementation<ITestParentService, TestParentService>();

            // Act
            var parentInstance = container.Get<ITestParentService>();

            // Assert
            Assert.AreSame(instance, parentInstance.ConstructorInjectedTestService);
            Assert.AreSame(instance, parentInstance.PropertyInjectedTestService);
        }

        [Test]
        public void Test_Get_Should_Inject_New_Instances_Of_Service_When_Service_Is_PerCall()
        {
            // Arrange
            var container = ContainerFactory.Create();

            container.SetImplementation<ITestService, TestService>();
            container.SetImplementation<ITestParentService, TestParentService>();

            // Act
            var parentInstance = container.Get<ITestParentService>();

            // Assert
            Assert.IsNotNull(parentInstance.ConstructorInjectedTestService);
            Assert.IsNotNull(parentInstance.PropertyInjectedTestService);
            Assert.AreNotSame(parentInstance.ConstructorInjectedTestService, parentInstance.PropertyInjectedTestService);
        }

        [Test]
        public void Test_CreateInstance_Should_Inject_Instance_Of_Service()
        {
            // Arrange
            var container = ContainerFactory.Create();

            var instance = new TestService();
            container.SetConstant<ITestService, TestService>(instance);

            // Act
            var parentInstance = container.CreateInstance<TestParentService>();

            // Assert
            Assert.AreSame(instance, parentInstance.ConstructorInjectedTestService);
            Assert.AreSame(instance, parentInstance.PropertyInjectedTestService);
        }

        [Test]
        public void Test_CreateInstance_Should_Inject_New_Instances_Of_Service_When_Service_Is_PerCall()
        {
            // Arrange
            var container = ContainerFactory.Create();

            container.SetImplementation<ITestService, TestService>();

            // Act
            var parentInstance = container.CreateInstance<TestParentService>();

            // Assert
            Assert.IsNotNull(parentInstance.ConstructorInjectedTestService);
            Assert.IsNotNull(parentInstance.PropertyInjectedTestService);
            Assert.AreNotSame(parentInstance.ConstructorInjectedTestService, parentInstance.PropertyInjectedTestService);
        }
    }
}
